#include <mFS/FsTypes.h>
#include <mFS/mConfig.h>
#include <Utils/Mem.h>
#include <Utils/StructDef.h>
#include <apdu/APDUParse.h>
#include <apdu/SwCode.h>
#include <apdu/CryptMacAP.h>
#include <cmd/CMDCryptMac.h>


void CMDCryptMac_MacInit(void)
{
	ApduCmd *pCmd;
	UINT16 nRet;

	pCmd = APDU_GetCmd();

	if(pCmd->CLA != 0x80)
	{
		APDU_SetRespond(0, ISOSW_CLA_ERROR);
		return ;
	}

	if(pCmd->LC < sizeof(CipherHeader) + 4 + 4)
	{
		APDU_SetRespond(0, ISOSW_LC_ERROR);
		return ;
	}

	if(pCmd->P1 != 0 || pCmd->P2 != 0)
	{
		APDU_SetRespond(0, ISOSW_P1P2_ERROR);
		return ;
	}

	nRet = CryptMacAP_MacInit(pCmd->pData, pCmd->LC);

	APDU_SetRespond(0, nRet);

	return ;
}

void CMDCryptMac_Mac(void)
{
	ApduCmd *pCmd;
	ApduRsp *pRsp;
	UINT16 nRet;

	pCmd = APDU_GetCmd();
	pRsp= APDU_GetRsp();

	if(pCmd->CLA != 0x80)
	{
		APDU_SetRespond(0, ISOSW_CLA_ERROR);
		return ;
	}

	if(pCmd->P1 != 0 || pCmd->P2 != 0)
	{
		APDU_SetRespond(0, ISOSW_P1P2_ERROR);
		return ;
	}

	if(pCmd->LE != 4 && pCmd->LE != 0)
	{
		APDU_SetRespond(0, ISOSW_LE_ERROR | 4);
		return ;
	}

	pCmd->LE = 4;

	nRet = CryptMacAP_Mac(pCmd->pData, pCmd->LC, pRsp->pData);

	if(nRet != ISOSW_SUCCESSFUL)
	{
		pCmd->LE = 0;
	}

	APDU_SetRespond(pCmd->LE, nRet);
	return ;
}

void CMDCryptMac_MacUpdate(void)
{
	ApduCmd *pCmd;
	UINT16 nRet;

	pCmd = APDU_GetCmd();

	if(pCmd->CLA != 0x80)
	{
		APDU_SetRespond(0, ISOSW_CLA_ERROR);
		return ;
	}

	if(pCmd->P1 != 0 || pCmd->P2 != 0)
	{
		APDU_SetRespond(0, ISOSW_P1P2_ERROR);
		return ;
	}

	nRet = CryptMacAP_MacUpdate(pCmd->pData, pCmd->LC);

	APDU_SetRespond(0, nRet);

	return ;
}

void CMDCryptMac_MacFinal(void)
{
	ApduCmd *pCmd;
	ApduRsp *pRsp;
	UINT16 nRet;

	pCmd = APDU_GetCmd();
	pRsp= APDU_GetRsp();

	if(pCmd->CLA != 0x80)
	{
		APDU_SetRespond(0, ISOSW_CLA_ERROR);
		return ;
	}

	if(pCmd->P1 != 0 || pCmd->P2 != 0)
	{
		APDU_SetRespond(0, ISOSW_P1P2_ERROR);
		return ;
	}

	if(pCmd->LE != 4 && pCmd->LE != 0)
	{
		APDU_SetRespond(0, ISOSW_LE_ERROR | 4);
		return ;
	}

	pCmd->LE = 4;

	nRet = CryptMacAP_MacFinal(pCmd->pData, pCmd->LC, pRsp->pData);

	if(nRet != ISOSW_SUCCESSFUL)
	{
		pCmd->LE = 0;
	}

	APDU_SetRespond(pCmd->LE, nRet);
	return ;
}
